""" bookscatalog module for BooksCatalog related views """
# usefool tools
from Products.CMFCore.utils import getToolByName
from Acquisition import aq_parent, aq_inner
from AccessControl import Unauthorized
from plone.memoize import instance
from Products.CMFPlone import PloneMessageFactory as _
from Products.statusmessages.interfaces import IStatusMessage

# ZCA stuff
from zope.interface import implements

# for the views
from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

# interfaces
from itx.bookscatalog.interfaces import IBooksCatalogView
from itx.bookscatalog.interfaces import ICatalogManager
from Products.CMFPlone.interfaces import IPloneSiteRoot

# kss stuff
from kss.core import kssaction
from plone.app.kss.plonekssview import PloneKSSView

# the BooksCatalog view
class BooksCatalogView(BrowserView):
    """View for BooksCatalog content type
    """
    implements(IBooksCatalogView)
    
    __call__ = ViewPageTemplateFile('templates/books_catalog.pt')
    
    def title(self):
        """Title of the context catalog
        """
        return self.context.pretty_title_or_id()
    
    def parent_url(self):
        """
        """
        portal_url = getToolByName(self.context, 'portal_url')
        plone_utils = getToolByName(self.context, 'plone_utils')
        portal_membership = getToolByName(self.context, 'portal_membership')
        
        obj = self.context
        
        checkPermission = portal_membership.checkPermission
        
        # Abort if we are at the root of the portal
        if IPloneSiteRoot.providedBy(self.context):
            return None
        
        
        # Get the parent. If we can't get it (unauthorized), use the portal
        parent = aq_parent(aq_inner(obj))
        
        # # We may get an unauthorized exception if we're not allowed to access#
        # the parent. In this case, return None
        try:
            if getattr(parent, 'getId', None) is None or \
                   parent.getId() == 'talkback':
                # Skip any Z3 views that may be in the acq tree;
                # Skip past the talkback container if that's where we are
                parent = aq_parent(aq_inner(parent))
                
            if not checkPermission('List folder contents', parent):
                return None
                
            return parent.absolute_url()
            
        except Unauthorized:
            return None        

    # In a better implementation, we could use a provider
    # to render the 'table' (the list of books shown in the
    # template) so the template would look much more clean,
    # easy to undestand and a bit more flexible (take note on that!)
    def getBooksList(self):
        """retrive books from BooksCatalog adapter,
        filtered by request attributes.
        Also, process the itx_search_form form
        """
        # Note for some itx plone programmer that is 
        # looking at this :)
        # If this code were to production, then it 
        # could be better to use formlib for the search form ;)
        try:
            catalog_manager = ICatalogManager(self.context)
        except:
            return []
        # populate a query with some general data
        query = dict(
            review_state = 'published',
            sort_on = 'Date',
            sort_order = 'descending',
            )   
        # check if the form was submitted
        if self.request.get("search_submit", None) is None:
            query['available'] = 1
            return catalog_manager.getBooks(query)
        # Note for a better implementation:
        # the 'available' (or stock, the one that it depends on)
        # property of a book is very likely
        # to change frequently, so it shouldn't be indexed
        # cause if so, we can get erroneous results when 
        # searching. Solution propossed:
        # add an utility for the CatalogManager that
        # manages the (always refreshed) availability of books, 
        # so if we want to know if a book is in stock, we look there.
        # For the proposs of this evaluation, lets just suppose the 
        # availability doesn't change very often, so an esporadic
        # refresh of the catalog is enough :)
        
        # We have to check the options and search criteria
        # and add them to the search query.
        no_stock = int(self.request.get('nostock_books', 0))
        # if the user had checked the box nostock_books (value=1),
        # it means that he/she wants to include books without
        # stock in the search results. 
        # If not, we mast filter this 'no-stock' books,
        # by querying for books whose property 'available'
        # is set to 1 (1 means True)
        if no_stock != 1:
            query['available'] = 1   
        # Now we check for the search criteria 
        # by default, criteria is ISBN, so its allways defined
        criteria = self.request.get('search_criteria', None)
        search_term = self.request.get('search_term', '')
        # Note: search_term is validated client-side
        # by default, search_term is ''
        if search_term != '':
            query[criteria] = search_term

        self.books = catalog_manager.getBooks(query)
        return self.books
    
    # To know if the catalog found any results.
    # It should be used after a call to getBooksList only,
    # if not, its useless
    def noBooks(self):        
        """
        """
        try:
            len_books = len(self.books)
        except: 
            pass
        else:
            if len_books == 0:
                return 1
            else:
                return 0
        return 0
    def deleteBooks(self):
        """delete books marked by a request key
        """
        books2del = self.request.form.get("delete_books", 
                                    self.request.get("delete_books", None))
        #import pdb; pdb.set_trace()
        if books2del is not None:
            catalog_manager = ICatalogManager(self.context)
            catalog_manager.delBooks(books2del)
        self.request.response.redirect(self.context.absolute_url())
    # we need a method to tell the role/permissions of the
    # actual member, so we can construct different pt's 
    # depending on that.
    def hasModifyPermissions(self):
        """Has the actual member modify permissions
        """
        pass

# this is for deletion of books with kss
# IMPORTANT: for now, this is breaking the site, so let's comment..
class manageBooks(PloneKSSView):
    @kssaction
    def delete_books(self):
        #import pdb; pdb.set_trace()
        books_list = self.request.get('delete_books', None)
        if books_list is not None:
            try:
                self.context.manage_delObjects(books_list)
            
            except AttributeError:
                # error msg
                IStatusMessage(self.request).addStatusMessage(
                    _(u'Some of the books on the list \
                        don\'t exist on the catalog.'))
            else:
                # now send the command back that we should refresh
                ksscore = self.getCommandSet('core')
                ksscore.deleteNode('.deleteMe')
                # ... and now the tricky part!
                # we have to chenge the 'table_row_class' of the 
                # remainder of the rows so that they look pretty
                # (odd files in lite grey and even files in grey)
                

